﻿// $Id: PathUtility.cs 64 2008-05-06 18:29:47Z nvivo $

using System;
using System.Reflection;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace DBLGen
{
    public static class PathUtility
    {
        /// <summary>
        /// Returns the path relative to the entry assembly, or the absolute path if the relative cannot be created.
        /// </summary>
        public static string GetRelativePath(string absolutePath)
        {
            string entryPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            return GetRelativePath(entryPath, absolutePath);
        }

        /// <summary>
        /// Returns the path relative to a base directory, or the absolute path if the relative cannot be created.
        /// </summary>
        public static string GetRelativePath(string baseDirectoryPath, string absolutePath)
        {
            if (baseDirectoryPath == null)
                throw new ArgumentNullException("basePath");

            absolutePath = Path.GetFullPath(absolutePath);

            if (baseDirectoryPath.EndsWith("\\"))
                baseDirectoryPath = baseDirectoryPath.Substring(0, baseDirectoryPath.Length - 1);

            if (absolutePath.EndsWith("\\"))
                absolutePath = absolutePath.Substring(0, absolutePath.Length - 1);

            // split path in parts

            string[] baseParts = baseDirectoryPath.Split(Path.DirectorySeparatorChar);
            string[] pathParts = absolutePath.Split(Path.DirectorySeparatorChar);

            // find out the common parts between them

            int baseLength = baseParts.Length;
            int common = 0;

            for (int i = 0; i < baseLength; i++)
            {
                if (String.Compare(baseParts[i], pathParts[i], true) == 0)
                    common++;
                else
                    break;
            }

            // if there is no common parts, return the absolute path

            if (common == 0)
                return Path.GetFullPath(absolutePath);

            // otherwise, continue

            StringBuilder sbPath = new StringBuilder(absolutePath.Length);

            // if there are still parts in the base path that are not common, add ".."

            if (common < baseLength)
            {
                for (int i = common; i < baseLength; i++)
                {
                    sbPath.Append("..");
                    sbPath.Append(Path.DirectorySeparatorChar);
                }
            }

            // then add the rest of the path 

            int lastPathIndex = pathParts.Length - 1;

            for (int i = common; i <= lastPathIndex; i++)
            {
                sbPath.Append(pathParts[i]);

                if (i != lastPathIndex)
                    sbPath.Append(Path.DirectorySeparatorChar);
            }

            return sbPath.ToString();
        }

        public static string GetAbsolutePath(string path)
        {
            string entryPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            return GetAbsolutePath(entryPath, path);
        }

        public static string GetAbsolutePath(string baseDirectoryPath, string path)
        {
            if (baseDirectoryPath == null)
                throw new ArgumentNullException(baseDirectoryPath);

            if (String.IsNullOrEmpty(path))
                return path;

            if (Path.IsPathRooted(path))
                return path;

            string absolutePath = Path.Combine(baseDirectoryPath, path);

            return absolutePath;
        }
    }
}
